// PriorityQueue.h
#ifndef __PRIORITYQUEUE_H__
#define __PRIORITYQUEUE_H__

#include <algorithm>
#include <functional>
#include <queue>
#include <vector>
#include "util/Pool.h"

// http://www.relisoft.com/resource/auto_vector.html
template <class T>
class ptr_greater : public std::binary_function <T,T,bool>
{
 public:
    bool operator () (T a, T b)
    {
        return *a > *b;
    }
};

// the ptr_greater means that PriorityQueue's T must be a pointer to a class that overloads operator>
template <typename T, typename C = ptr_greater<T> >
class PriorityQueue : public std::priority_queue<T, std::vector<T, pool_allocator<T> >, C> , public Container<T> {
 public:
    NEW_DELETE_OPERATORS_INLINE_H(PriorityQueue<T>,NoSuper);

    PriorityQueue () {};
    virtual ~PriorityQueue () {};

    // add puts a new item into the queue
    void add (T t) {
        push(t);
    }

    // remove takes an item from the queue
    T remove () {
        T t = this->top();
        this->pop();
        return t;
    }

    // peek looks at the head of the queue without removing it
    T peek () {
        return this->top();
    }

    T containerRemove (T t) {
        typename std::vector<T, pool_allocator<T> >::iterator i = std::find(this->c.begin(), this->c.end(), t);
        if (i == this->c.end()) {
            return 0;
        }
        this->c.erase(i);
        make_heap(this->c.begin(), this->c.end(), this->comp);
        return t;
    }

    // length allows the caller to determine how full the queue in
    // question currently is . . . .
    int getLength () { 
        return this->size(); 
    }

    //
    // isEmpty allows the caller to determine if anything is in the queue
    bool isEmpty () { 
        return this->empty(); 
    }
};

#endif // __PRIORITYQUEUE_H__
